//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************

#include "PrimaryGeneratorMessenger.hh"

#include "G4UIcmdWithADouble.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIdirectory.hh"
#include "PrimaryGeneratorAction.hh"

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....

PrimaryGeneratorMessenger::PrimaryGeneratorMessenger(PrimaryGeneratorAction* gen) : _fGen(gen)
{
    _fVerbose = _fGen->GetVerbose();
    if (_fVerbose) G4cout << "PrimaryGeneratorMessenger: Construct " << G4endl;

    _fGunDir = new G4UIdirectory("/testem/gun/");
    _fGunDir->SetGuidance("commands to define gun");

    ///=====================================
    fBeamXCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/beamX", this);
    fBeamXCmd->SetGuidance("Set X position of the center of the beam.");
    fBeamXCmd->SetParameterName("beamX", true);
    fBeamXCmd->SetUnitCategory("Length");
    fBeamXCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fBeamYCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/beamY", this);
    fBeamYCmd->SetGuidance("Set Y position of the center of the beam.");
    fBeamYCmd->SetParameterName("beamY", true);
    fBeamYCmd->SetUnitCategory("Length");
    fBeamYCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fBeamZCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/beamZ", this);
    fBeamZCmd->SetGuidance("Set Z of the entry point of the beam.");
    fBeamZCmd->SetParameterName("beamZ", true);
    fBeamZCmd->SetUnitCategory("Length");
    fBeamZCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fBeamECmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/beamE", this);
    fBeamECmd->SetGuidance("Set the beam kinetic energy");
    fBeamECmd->SetParameterName("beamE", false);
    fBeamECmd->SetUnitCategory("Energy");
    fBeamECmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fSigmaXCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/sigmaX", this);
    fSigmaXCmd->SetGuidance("Set the beam Gussian width for X");
    fSigmaXCmd->SetParameterName("sigmaX", false);
    fSigmaXCmd->SetRange("sigmaX>=0.");
    fSigmaXCmd->SetUnitCategory("Length");
    fSigmaXCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fSigmaYCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/sigmaY", this);
    fSigmaYCmd->SetGuidance("Set the beam Gussian width for Y");
    fSigmaYCmd->SetParameterName("sigmaY", false);
    fSigmaYCmd->SetRange("sigmaY>=0.");
    fSigmaYCmd->SetUnitCategory("Length");
    fSigmaYCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fSigmaZCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/sigmaZ", this);
    fSigmaZCmd->SetGuidance("Set the beam Gussian width for Y");
    fSigmaZCmd->SetParameterName("sigmaZ", false);
    fSigmaZCmd->SetRange("sigmaZ>=0.");
    fSigmaZCmd->SetUnitCategory("Length");
    fSigmaZCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fSigmaECmd = new G4UIcmdWithADouble("/testem/gun/sigmaE", this);
    fSigmaECmd->SetGuidance("Set the relative beam Gussian width for energy");
    fSigmaECmd->SetParameterName("sigmaE", false);
    fSigmaECmd->SetRange("sigmaE>=0.");
    fSigmaECmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fDisTypeXYCmd = new G4UIcmdWithAString("/testem/gun/distypeXY", this);
    fDisTypeXYCmd->SetGuidance("Set the type of XY distribution (gauss,flat)");
    fDisTypeXYCmd->SetParameterName("distypeXY", false);
    fDisTypeXYCmd->SetCandidates("gauss flat");
    fDisTypeXYCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fDisTypeECmd = new G4UIcmdWithAString("/testem/gun/distypeE", this);
    fDisTypeECmd->SetGuidance("Set the type of energy distribution (gauss,flat)");
    fDisTypeECmd->SetParameterName("distypeE", false);
    fDisTypeECmd->SetCandidates("gauss flat");
    fDisTypeECmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fThetaCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/sigmaTheta", this);
    fThetaCmd->SetGuidance("Set the beam sigmaTheta in degrees.");
    fThetaCmd->SetParameterName("sigmaTheta", false);
    fThetaCmd->SetRange("sigmaTheta>=0.");
    fThetaCmd->SetUnitCategory("Angle");
    fThetaCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fDisTypeThetaCmd = new G4UIcmdWithAString("/testem/gun/distypeTheta", this);
    fDisTypeThetaCmd->SetGuidance("Set the type of theta distribution (gauss,flat)");
    fDisTypeThetaCmd->SetParameterName("distypeTheta", false);
    fDisTypeThetaCmd->SetCandidates("gauss flat");
    fDisTypeThetaCmd->AvailableForStates(G4State_PreInit, G4State_Idle);

    ///=====================================
    fSpotDeltaYCmd = new G4UIcmdWithADoubleAndUnit("/testem/gun/spotDeltaY", this);
    fSpotDeltaYCmd->SetGuidance("Set Y deviation of the center of the spot in virtual source plane.");
    fSpotDeltaYCmd->SetParameterName("spotDeltaY", true);
    fSpotDeltaYCmd->SetUnitCategory("Length");
    fSpotDeltaYCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....

PrimaryGeneratorMessenger::~PrimaryGeneratorMessenger()
{
    delete fBeamXCmd;
    delete fBeamYCmd;
    delete fBeamZCmd;
    delete fBeamECmd;

    delete fSigmaXCmd;
    delete fSigmaYCmd;
    delete fSigmaZCmd;
    delete fSigmaECmd;

    delete fDisTypeXYCmd;
    delete fDisTypeECmd;

    delete fThetaCmd;
    delete fDisTypeThetaCmd;
    delete fSpotDeltaYCmd;

    delete _fGunDir;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....

void PrimaryGeneratorMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
{
    if (_fVerbose) G4cout << "PrimaryGeneratorMessenger: Next command value = " << newValue << G4endl;

    if (command == fBeamXCmd)
    {
        _fGen->SetBeamX(fBeamXCmd->GetNewDoubleValue(newValue));
    }
    if (command == fBeamYCmd)
    {
        _fGen->SetBeamY(fBeamYCmd->GetNewDoubleValue(newValue));
    }
    if (command == fBeamZCmd)
    {
        _fGen->SetBeamZ(fBeamZCmd->GetNewDoubleValue(newValue));
    }
    if (command == fBeamECmd)
    {
        _fGen->SetBeamEnergy(fBeamECmd->GetNewDoubleValue(newValue));
    }
    if (command == fSigmaXCmd)
    {
        _fGen->SetBeamSigmaX(fSigmaXCmd->GetNewDoubleValue(newValue));
    }
    if (command == fSigmaYCmd)
    {
        _fGen->SetBeamSigmaY(fSigmaYCmd->GetNewDoubleValue(newValue));
    }
    if (command == fSigmaZCmd)
    {
        _fGen->SetBeamSigmaZ(fSigmaZCmd->GetNewDoubleValue(newValue));
    }
    if (command == fSigmaECmd)
    {
        _fGen->SetBeamSigmaE(fSigmaECmd->GetNewDoubleValue(newValue));
    }
    if (command == fDisTypeXYCmd)
    {
        _fGen->SetDisTypeXY(newValue);
    }
    if (command == fDisTypeECmd)
    {
        _fGen->SetDisTypeE(newValue);
    }
    if (command == fThetaCmd)
    {
        _fGen->SetSigmaTheta(fThetaCmd->GetNewDoubleValue(newValue));
    }

    if (command == fDisTypeThetaCmd)  //2022.10.18
    {
        _fGen->SetDisTypeTheta(newValue);
    }

    if (command == fSpotDeltaYCmd)  //2023.6.20, for QA test
    {
        _fGen->SetSpotDeltaY(fSpotDeltaYCmd->GetNewDoubleValue(newValue));
    }

    if (_fVerbose) G4cout << "PrimaryGeneratorMessenger: O'K " << G4endl;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....